<template>
  <div id="excel-export">
    <slot name="custom" v-if="isCustom"></slot>

    <a-button ghost type="primary" @click="getTableData" v-else>
      导出excel
    </a-button>

    <a-modal
      v-if="visible"
      v-model="visible"
      :title="modelTitle"
      :maskClosable="false"
      :closable="false"
    >
      <template #footer>
        <a-button
          type="primary"
          ghost
          v-if="isAbnormal"
          :loading="btnLoading"
          @click="resetExport"
        >
          重新导出
        </a-button>
        <a-button
          type="primary"
          ghost
          v-if="isAbnormal"
          :loading="btnLoading"
          @click="getTableData"
        >
          继续导出
        </a-button>
        <a-button :loading="btnLoading" @click="handleClose"> 关闭 </a-button>
      </template>
      <a-progress
        :percent="percent"
        :status="progressStatus"
        class="progress"
      />
    </a-modal>
  </div>
</template>
<script>
import * as XLSX from "xlsx";

export default {
  props: {
    //自定义过滤函数
    filterFunction: {
      type: Function,
      default: null,
    },
    //sheet名
    ws_name: {
      type: String,
      default: "Sheet",
    },
    //导出的excel的表名
    filename: {
      type: String,
      default: "Excel" + new Date().getTime(),
    },
    //拆分成每个表多少条数据，需要搭配isSplit属性一起使用
    splitNum: {
      type: Number,
      default: 10e4,
    },
    //是否拆分
    isSplit: {
      type: Boolean,
      default: false,
    },
    //模态框标题
    modelTitle: {
      type: String,
      default: "导出excel",
    },
    //是否自定义dom,如果采用插槽，需要开启该属性，否则dom为默认button
    isCustom: {
      type: Boolean,
      default: false,
    },
    // 导出的数据表的表头
    tableTitleData: {
      type: Array,
      required: true,
      default: () => [],
    },
    //请求数据的api函数
    asyncDataApi: {
      type: Function,
      default: () => {},
    },
    //请求参数
    listQuery: {
      type: Object,
      default: () => ({}),
    },
  },
  data() {
    return {
      ws: null,
      isAbnormal: false,
      btnLoading: false,
      progressStatus: "active",
      visible: false,
      percent: 0,
      tableData: [],
      page: 1,
    };
  },
  computed: {
    // 导出的数据表的表头
    tableTitle() {
      return this.tableTitleData.map((item) => {
        return item.title;
      });
    },
    //导出数据表的表头的code
    tableCode() {
      return this.tableTitleData.map((item) => {
        return item.code;
      });
    },
  },
  watch: {
    percent: {
      handler(newVal) {
        if (newVal > 100) {
          this.progressStatus = "success";
          setTimeout(() => {
            this.handleClose();
          }, 500);
        }
      },
    },
  },
  methods: {
    //按照指定的title顺序映射排序数组对象
    sortData(data, tit_code) {
      const newData = [];
      data.forEach((item) => {
        const newObj = {};
        tit_code.forEach((v) => {
          newObj[v] = item[v] || "";
        });
        newData.push(newObj);
      });
      return newData;
    },
    resetExport() {
      this.resetModel();
      this.statrExport();
    },

    handleClose() {
      console.log("close");
      this.resetModel();
      this.visible = false;
    },
    resetModel() {
      this.percent = 0;
      this.progressStatus = "active";
      this.isAbnormal = false;
      this.tableData = [];
      this.page = 1;
    },
    //获取进度条百分比
    getPersent(res) {
      const persent_num =
        ((res.pagetation.currentPage * res.pagetation.pageSize) /
          res.pagetation.total) *
        100;
      this.percent = parseInt(persent_num) - 1;
    },

    async statrExport() {
      if (!this.asyncDataApi) {
        return new Promise(new Error("asyncDataApi is required"));
      }

      this.ws = XLSX.utils.aoa_to_sheet([this.tableTitle]);
      await this.getTableData();

      return;
    },
    //请求导出的数据和标题
    async getTableData() {
      if (!this.asyncDataApi)
        return new Promise(new Error("asyncDataApi is required"));

      this.visible = true;
      this.btnLoading = true;

      try {
        const res = await this.asyncDataApi({
          ...this.listQuery,
          page: this.page,
        });
        let apiData = res.data;
        apiData = this.sortData(apiData, this.tableCode);

        if (this.filterFunction) {
          apiData = this.filterFunction(apiData);
        }

        // this.tableData = [...this.tableData, ...apiData];

        // const data1 = [
        //   { "Header 1": 3, "Header 2": 4 },
        //   { "Header 1": 5, "Header 2": 6 },
        // ];

        XLSX.utils.sheet_add_json(this.ws, apiData, {
          skipHeader: true,
          origin: (this.page - 1) * res.pagetation.pageSize + 1,
        });

        this.page = res.pagetation.currentPage + 1;

        this.getPersent(res);

        if (res.pagetation.currentPage < res.pagetation.page) {
          this.getTableData();
          return;
        }

        const total = res.pagetation.total;
        if (this.isSplit || total > 10e4) {
          this.splitExport();
        } else {
          this.exportExcel(
            this.tableData,
            this.filename + ".xlsx",
            this.ws_name
          );
        }
      } catch (error) {
        console.log(error);
        this.btnLoading = false;
        this.progressStatus = "exception";
      }
    },
    //拆分成多个excel导出
    splitExport() {
      const num = Math.ceil(this.tableData.length / this.splitNum);

      for (let i = 0; i < num; i++) {
        const exportData = this.tableData.slice(
          i * this.splitNum,
          (i + 1) * this.splitNum
        );

        this.exportExcel(
          exportData,
          this.filename + (i + 1) + ".xlsx",
          this.ws_name + (i + 1)
        );
      }
    },
    //导出所有数据到一个excel
    exportExcel(exportData, fileName, sheetName) {
      const newData = exportData.map((item) => Object.values(item));

      //添加表头
      newData.unshift(this.tableTitle);
      // 文件名称
      const filename = fileName;
      //Excel第一个sheet的名称
      const ws_name = sheetName;

      // 创建sheet
      //const ws = XLSX.utils.aoa_to_sheet(newData);
      // const ws = XLSX.utils.aoa_to_sheet([
      //   ["Header 1", "Header 2"],
      //   [1, 2],
      // ]);

      // const data1 = [
      //   { "Header 1": 3, "Header 2": 4 },
      //   { "Header 1": 5, "Header 2": 6 },
      // ];
      // XLSX.utils.sheet_add_json(ws, data1, {
      //   skipHeader: true,
      //   origin: 3,
      // });

      // const data2 = [
      //   { "Header 1": 7, "Header 2": 8 },
      //   { "Header 1": 9, "Header 2": 10 },
      // ];

      // XLSX.utils.sheet_add_json(ws, data2, {
      //   skipHeader: true,
      //   origin: 5,
      // });

      // 创建wokbook
      const wb = XLSX.utils.book_new();
      // 将数据添加到工作薄
      XLSX.utils.book_append_sheet(wb, this.ws, ws_name);
      // 导出文件
      XLSX.writeFile(wb, filename);

      this.percent += 2;
      this.btnLoading = false;
      this.$message.success("导出成功");
    },
  },
};
</script>
<style scoped lang="less"></style>
